package com.steakliu.netty.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.CharsetUtil;

import java.util.HashMap;
import java.util.Map;

import static io.netty.handler.codec.http.HttpUtil.is100ContinueExpected;

/**
 * 功能说明：
 * <p>
 * Original @Author: steakliu-刘牌, 2022-09-04  00:06
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
public class HttpServer {
    private Integer port;

    public HttpServer(Integer port) {
        this.port = port;
    }

    public static void main(String[] args) {
        HttpServer httpServer = new HttpServer(8080);
        httpServer.startServer();
    }

    public void startServer() {
        ServerBootstrap bootstrap = new ServerBootstrap();
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            bootstrap.group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //.localAddress(port)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new HttpServerCodec())
                                    .addLast("httpAggregator", new HttpObjectAggregator(512 * 1024))
                                    .addLast(new SimpleChannelInboundHandler<FullHttpRequest>() {
                                        @Override
                                        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
                                            //100 Continue
                                            if (is100ContinueExpected(req)) {
                                                ctx.write(new DefaultFullHttpResponse(
                                                        HttpVersion.HTTP_1_1,
                                                        HttpResponseStatus.CONTINUE));
                                            }
                                            // 获取请求的uri
                                            String uri = req.uri();
                                            Map<String, String> resMap = new HashMap<>();
                                            resMap.put("method", req.method().name());
                                            resMap.put("uri", uri);
                                            String msg = "<html><head><title>test</title></head><body>你请求uri为：" + uri + "</body></html>";
                                            // 创建http响应
                                            FullHttpResponse response = new DefaultFullHttpResponse(
                                                    HttpVersion.HTTP_1_1,
                                                    HttpResponseStatus.OK,
                                                    Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
                                            // 设置头信息
                                            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
                                            //response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
                                            // 将html write到客户端
                                            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                                        }
                                    });
                        }
                    });

            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
